package com.bajiao.service.user.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.bajiao.common.constant.CommonConstant;
import com.bajiao.common.constant._Whole;
import com.bajiao.common.exception.DataHandleException;
import com.bajiao.common.util.*;
import com.bajiao.common.util.vans.NameTool;
import com.bajiao.common.util.vans.VansTool;
import com.bajiao.service.account.AccountService;
import com.bajiao.service.config.ConfigService;
import com.bajiao.service.giveRule.GiveRuleService;
import com.bajiao.service.user.UserCouponService;
import com.bajiao.third.utils.WxPayUtils;
import com.bajiao.vo.coupon.CouponResponse;
import com.bajiao.vo.order.OrderAdmin;
import com.bajiao.vo.user.*;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.extension.service.additional.update.impl.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bajiao.entity.account.Account;
import com.bajiao.entity.user.User;
import com.bajiao.mapper.user.UserMapper;
import com.bajiao.service.user.UserService;
import org.apache.xmlbeans.impl.common.NameUtil;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description: 普通用户
 * @Author: FanJq
 * @Date: 2024-10-10
 * @Version: V1.0
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Lazy
    @Resource
    private AccountService accountService;
    @Resource
    private GiveRuleService giveRuleService;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private UserCouponService userCouponService;
    @Resource
    private WxPayUtils wxPayUtils;
    @Resource
    private ConfigService configService;


    /**
     * @Description
     * 用户注册
     * @date 2024/12/19 16:53
     * @author FanJq
     * @param mobile
     * @param openId
     * @param unionId
     * @param nickname
     * @param avatar
     * @param sex
     * @param inviteCode
     * @return {@link User}
    */
    @Override
    public User wxRegister(String mobile, String openId, String unionId, String nickname, String avatar, Integer sex, String inviteCode) {
        //用户
        User user = new User();
        user.setId(IDGeneratorUtils.getStringId());
        user.setNickname(StrUtil.isBlank(nickname) ? NameTool.getName() : nickname);
        String salt = oConvertUtils.randomGen(8);
        user.setPassword(PasswordUtil.encrypt(_Whole.init_cipher, "", salt));
        user.setSalt(salt);
        //@create by FanJq 2024/12/20 17:31 2024/12/1319718156327198720.png
        user.setAvatar(StrUtil.isBlank(avatar) ? "2025/02/19/1341842847200055296.jpg" : avatar);
        user.setMobile(mobile);
        user.setMobileEncrypt(VansTool.encryptMobile(mobile));
        user.setSex(sex);
        user.setInviteCode(getInviteCode());
        user.setOpenId(openId);
        user.setUnionId(unionId);
        //@create by FanJq 2024/12/12 9:39 处理邀请人逻辑
        this.inviterLogic(inviteCode, user);
        super.save(user);
        //生成账户
        Account account = new Account();
        account.setUserId(user.getId());
        accountService.save(account);
        //@create by FanJq 2024/12/12 11:24 处理注册赠送逻辑
        this.registerGiveLogic(user.getId());
        return user;
    }

    /**
     * @Description
     * App注册
     * @date 2024/12/25 17:45
     * @author FanJq
     * @param mobile
     * @param cipher
     * @param inviteCode
     * @return {@link User}
    */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public User appRegister(String mobile, String cipher, String inviteCode) {
        //用户
        User user = new User();
        user.setId(IDGeneratorUtils.getStringId());
        user.setNickname(NameTool.getName());
        String salt = oConvertUtils.randomGen(8);
        user.setPassword(PasswordUtil.encrypt(cipher, "", salt));
        user.setSalt(salt);
        //@create by FanJq 2024/12/20 17:31 2024/12/1319718156327198720.png
        user.setAvatar("2025/02/19/1341842847200055296.jpg");
        user.setMobile(mobile);
        user.setMobileEncrypt(VansTool.encryptMobile(mobile));
        user.setInviteCode(getInviteCode());
        //@create by FanJq 2024/12/12 9:39 处理邀请人逻辑
        this.inviterLogic(inviteCode, user);
        super.save(user);
        //生成账户
        Account account = new Account();
        account.setUserId(user.getId());
        accountService.save(account);
        //@create by FanJq 2024/12/12 11:24 处理注册赠送逻辑
        this.registerGiveLogic(user.getId());
        return user;
    }

    /**
     * @Description
     * 修改密码
     * @date 2024/12/25 17:59
     * @author FanJq
     * @param user
     * @param cipher
     * @return
    */
    @Override
    public void modifyCipher(User user, String cipher) {
        String salt = oConvertUtils.randomGen(8);
        user.setPassword(PasswordUtil.encrypt(cipher, "", salt));
        user.setSalt(salt);
        super.updateById(user);
        if (redisUtil.hasKey(CommonConstant.SIGN_USER_ID + user.getId())) {
            long expire = redisUtil.getExpire(CommonConstant.SIGN_USER_ID + user.getId());
            redisUtil.set(CommonConstant.SIGN_USER_ID + user.getId(), user, expire);
        }
    }

    /**
     * @Description
     * 根据openID获取用户信息
     * @date 2024/12/11 17:52
     * @author FanJq
     * @param openId
     * @return {@link User}
    */
    @Override
    public User getByOpenId(String openId) {
        return this.lambdaQuery().eq(User::getOpenId, openId).one();
    }

    /**
     * @Description
     * 根据手机号查下删除状态为否的用户
     * @date 2024/12/12 9:31
     * @author FanJq
     * @param mobile
     * @return {@link User}
    */
    @Override
    public User queryByMobileAndNotDelFlag(String mobile) {
        return baseMapper.queryByMobileAndNotDelFlag(mobile);
    }

    /**
     * @Description
     * 用户详情
     * @date 2024/12/12 9:31
     * @author FanJq
     * @param user
     * @return {@link UserInfo}
    */
    @Override
    public UserInfo getUserInfo(User user) {
        UserInfo vo = FastJsonHelper.beanToBean(user, UserInfo.class);
        vo.setInterestList(Arrays.asList(vo.getInterest().split(StringPool.COMMA)));
        return vo;
    }

    /**
     * @Description
     * 修改用户资料
     * @date 2024/12/23 10:18
     * @author FanJq
     * @param userId
     * @return {@link UserInfo}
    */
    @Override
    public UserInfo modify(String userId, UserInfo request) {
        Boolean modify = Boolean.FALSE;
        User user = super.getById(userId);
        LambdaUpdateChainWrapper<User> updateSql = super.lambdaUpdate().eq(User::getId, userId);
        if (StrUtil.isNotBlank(request.getNickname()) && !user.getNickname().equals(request.getNickname())) {
            updateSql.set(User::getNickname, request.getNickname());
            user.setNickname(request.getNickname());
            modify = Boolean.TRUE;
        }
        if (StrUtil.isNotBlank(request.getAvatar()) && !user.getAvatar().equals(request.getAvatar())) {
            updateSql.set(User::getAvatar, request.getAvatar());
            user.setAvatar(request.getAvatar());
            modify = Boolean.TRUE;
        }
        if (ObjectUtil.isNotNull(request.getSex()) && user.getSex().intValue() != request.getSex().intValue()) {
            updateSql.set(User::getSex, request.getSex());
            user.setSex(request.getSex());
            modify = Boolean.TRUE;
        }
        if (ObjectUtil.isNotNull(request.getAge()) && !StrUtil.equals(request.getAge(), user.getAge())) {
            updateSql.set(User::getAge, request.getAge());
            user.setAge(request.getAge());
            modify = Boolean.TRUE;
        }
        if (StrUtil.isNotBlank(request.getInterest()) && !user.getInterest().equals(request.getInterest())) {
            updateSql.set(User::getInterest, request.getInterest());
            user.setInterest(request.getInterest());
            modify = Boolean.TRUE;
        }
        if (modify) {
            if (updateSql.update()) {
                long expire = redisUtil.getExpire(CommonConstant.SIGN_USER_ID + user.getId());
                redisUtil.set(CommonConstant.SIGN_USER_ID + user.getId(), user, expire);
            }
        }
        return request;
    }

    public static void main(String[] args) {
        System.out.println(oConvertUtils.randomGen(12));
    }

    /**
     * @Description
     * 根据邀请码获取用户
     * @date 2024/12/12 9:28
     * @author FanJq
     * @param inviteCode
     * @return {@link User}
    */
    @Override
    public User getByInviteCode(String inviteCode) {
        User user = super.lambdaQuery().eq(User::getInviteCode, inviteCode).one();
        return user;
    }

    /**
     * @Description
     * 设置用户兴趣
     * @date 2024/12/13 15:06
     * @author FanJq
     * @param userId
     * @param interest
     * @return
    */
    @Override
    @Async("taskExecutor")
    public void setInterest(String userId, String interest) {
        super.lambdaUpdate().set(User::getInterest, interest).eq(User::getId, userId).update();
        long expire = redisUtil.getExpire(CommonConstant.SIGN_USER_ID + userId);
        if (ObjectUtil.isNotNull(expire) && expire > _Whole.ZERO) {
            User user = (User) redisUtil.get(CommonConstant.SIGN_USER_ID + userId);
            if (ObjectUtil.isNotNull(user)) {
                user.setInterest(interest);
                redisUtil.set(CommonConstant.SIGN_USER_ID + userId, user, expire);
            }
        }
    }

    /**
     * @Description
     * 获取用户账户信息
     * @date 2024/12/14 16:46
     * @author FanJq
     * @param userId
     * @return {@link Account}
    */
    @Override
    public Account getAccount(String userId) {
        return accountService.queryByUserId(userId);
    }

    /**
     * @Description
     * 资金变动
     * @date 2024/12/12 10:11
     * @author FanJq
     * @param changeMoney 变化金额
     * @param billType 1:收入 2：支出
     * @param orderNo 订单编号
     * @param title 标题
     * @param type 流水类型 1:充值 2:购买优惠券 3:购买商品 4:优惠券退款 5:商品退款 6:注册赠送 7:邀请奖励 99:平台赠送
     * @return
     */
    @Override
    public void changeMoney(String userId, BigDecimal changeMoney, Integer billType, String orderNo, String title, int type) {
        accountService.changeMoney(userId, changeMoney, billType, orderNo, title, type);
    }

    /**
     * @Description
     * 用户资产
     * @date 2024/12/20 18:01
     * @author FanJq
     * @param userId
     * @return {@link UserProperty}
    */
    @Override
    public UserProperty getProperty(String userId) {
        UserProperty response = new UserProperty();
        response.setId(userId);
        response.setCouponTotal(userCouponService.getUserHasCount(userId, null));
        Account account = this.getAccount(userId);
        response.setBalance(account.getMoney().stripTrailingZeros().toPlainString());
        BigDecimal consumeAmount = baseMapper.getUserConsumeAmount(userId);
        response.setConsumeAmount(consumeAmount.stripTrailingZeros().toPlainString());
        return response;
    }

    /**
     * @Description
     * 获取邀请二维码
     * @date 2024/12/23 16:01
     * @author FanJq
     * @param inviteCode
     * @param source applet-小程序 ios-ios android-安卓
     * @return {@link String}
    */
    @Override
    public String getInviteCode(String inviteCode, String source) {
        if (source.equals("applet")) {
            String base64Flag = "data:image/png;base64,";
            String unlimitedQRCode = wxPayUtils.getUnlimitedQRCode(inviteCode);
            return base64Flag + unlimitedQRCode;
        } else {
            String h5Url = configService.getValue("invite", "h5");
            return QrCodeUtil.generateAsBase64(h5Url + inviteCode, new QrConfig(), "png");
        }
    }

    /**
     * @Description
     * 获取邀请记录
     * @date 2024/12/23 17:20
     * @author FanJq
     * @param userId
     * @return {@link List< InviteRecord>}
    */
    @Override
    public List<InviteRecord> getInviteRecord(String userId) {
        List<User> userList = super.lambdaQuery()
                .select(User::getAvatar, User::getNickname, User::getCreateTime)
                .eq(User::getSuperId, userId)
                .orderByDesc(User::getCreateTime)
                .list();
        List<InviteRecord> recordList = userList.stream().map(user -> {
            InviteRecord record = FastJsonHelper.beanToBean(user, InviteRecord.class);
            return record;
        }).collect(Collectors.toList());
        return recordList;
    }

    /**
     * @Description
     * 获取用户优惠券
     * @date 2024/12/24 17:04
     * @author FanJq
     * @param userId
     * @return {@link List< CouponResponse>}
    */
    @Override
    public List<CouponResponse> getUserCoupon(String userId) {
        return userCouponService.getByUserId(userId);
    }

    /**
     * @Description
     * 管理后台列表
     * @date 2025/1/2 11:16
     * @author FanJq
     * @param request
     * @return {@link List< UserAdmin>}
    */
    @Override
    public List<UserAdmin> getUserAdminList(UserAdmin request) {
        List<UserAdmin> userAdminList = super.baseMapper.getUserAdminList(request);
        userAdminList.stream()
                .filter(i -> StrUtil.isNotBlank(i.getSuperNickname()))
                .forEach(model -> {
                    String[] superUser = model.getSuperNickname().split(StringPool.COMMA);
                    model.setSuperNickname(superUser[0]);
                    model.setSuperMobile(superUser[1]);
        });
        return userAdminList;
    }

    /**
     * @Description
     * 核销列表
     * @date 2025/1/9 16:45
     * @author FanJq
     * @param keywords
     * @param orderNo
     * @param storeTitle
     * @param title
     * @param createTimeBegin
     * @param createTimeEnd
     * @return {@link List< UserVerify>}
    */
    @Override
    public List<UserVerify> getVerifyList(String keywords, String orderNo, String storeTitle, String title, String createTimeBegin, String createTimeEnd) {
        if (StrUtil.isAllNotBlank(createTimeBegin, createTimeEnd))
            createTimeEnd = createTimeEnd + " 23:59:59";
        List<UserVerify> resultList = super.baseMapper.getVerifyList(keywords, orderNo, storeTitle, title, createTimeBegin, createTimeEnd);
        return resultList;
    }

    /**
     * @Description
     * 生成邀请码
     * @date 2024/12/12 9:29
     * @author FanJq
     * @param
     * @return {@link String}
    */
    public String getInviteCode(){
        String inviteCode = oConvertUtils.randomGen(_Whole.EIGHT);
        User user = this.getByInviteCode(inviteCode);
        if (ObjectUtil.isNotNull(user))
            this.getInviteCode();
        return inviteCode;
    }

    /**
     * @Description
     * 处理邀请人逻辑
     * @date 2024/12/12 9:40
     * @author FanJq
     * @param inviteCode
     * @param user
     * @return
    */
    public void inviterLogic(String inviteCode, User user) {
        if (StrUtil.isBlank(inviteCode))
            return;
        User superUser = this.getByInviteCode(inviteCode);
        if (ObjectUtil.isNull(superUser))
            throw new DataHandleException("邀请人不存在");
        user.setSuperId(superUser.getId());
        //@create by FanJq 2024/12/12 10:03 获取邀请的赠送金额
        BigDecimal giveAmount = giveRuleService.getGiveAmount("INVITE_GIVE_COIN");
        //@create by FanJq 2024/12/12 10:31 赠送邀请收益
        this.changeMoney(superUser.getId(), giveAmount, _Whole.ONE, user.getId(), "邀请收益", _Whole.SEVEN);
    }

    /**
     * @Description
     * 注册奖励
     * @date 2024/12/12 11:23
     * @author FanJq
     * @param userId
     * @return
    */
    public void registerGiveLogic(String userId) {
        //@create by FanJq 2024/12/12 11:16 获取注册的赠送金额
        BigDecimal giveAmount = giveRuleService.getGiveAmount("REGISTER_GIVE_COIN");
        //@create by FanJq 2024/12/12 10:31 赠送邀请收益
        this.changeMoney(userId, giveAmount, _Whole.ONE, userId, "注册奖励", _Whole.SIX);
    }
}
